﻿namespace OneWorks.Utils.Metadata
{
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;
    using FluentData;
    using Interface;
    using Entity;
    using System;

    public abstract class MetadataHandler : IDataBase, ITable, IColumn
    {
        //protected IDbUtility DbUtility;

        protected IDbContext Context;

        protected IConnection Connection;

        protected IDbProvider Provider;

        protected  MetadataHandler(IDbProvider dbProvider,IConnection connection)
        {
            Connection = connection;
            Provider = dbProvider;
            Context =new DbContext().ConnectionString(Connection.ToString(), Provider);
        }

        #region  protected

        /// <summary>
        /// 获取所有数据库信息的字符串
        /// </summary>
        /// <returns></returns>
        protected abstract string GetDataBaseSting();

        /// <summary>
        /// 获取所有表信息字符串
        /// </summary>
        /// <returns></returns>
        protected abstract string GetDataTableString(string dbName = "");

        /// <summary>
        /// 获取所有字段字符串
        /// </summary>
        /// <returns></returns>
        protected abstract string GetDataColumnString(string tbName, string dbName = "");

        /// <summary>
        /// 查询数据库Table转换为数据库对象
        /// </summary>
        /// <param name="database"></param>
        /// <param name="reader"> </param>
        /// <returns></returns>
        protected abstract void DoDataBase(Database database, FluentData.IDataReader reader);


        /// <summary>
        /// 查询数据库Table转换为数据库对象
        /// </summary>
        /// <param name="datable"></param>
        /// <returns></returns>
        protected abstract List<Table> DoTable(DataTable datable);


        protected abstract List<Column> DoColumn(DataTable dataTable);

        #endregion

        #region public

        public List<Database> GetDataBases(bool include = false)
        {
            string sql = this.GetDataBaseSting();
            try
            {
                List<Database> databases = Context.Sql(sql).QueryMany<Database>();
                if (include)
                {
                    foreach (var database in databases)
                    {
                        database.ConnectionString = Connection.ToString();
                        database.DbType = Provider.ToString();
                        database.Tables = GetTables(database.Name);
                    }
                }
                return databases;
            }
            catch (Exception exception)
            {
                Log.LogHandler.Log.Error("获取元数据数据库列表出现问题,sql:" + sql, exception);
                return new List<Database>();
            }

        }

        public Database FindDataBase(string dbName, bool include = false)
        {
            string sql = this.GetDataBaseSting();
            try
            {
                List<Database> databases = Context.Sql(sql).QueryMany<Database>();
                Database database = databases.FirstOrDefault(t => t.Name == dbName);
                if (database != null && include)
                {
                    database.ConnectionString = Connection.ToString();
                    database.DbType = Provider.ToString();
                    database.Tables = GetTables(database.Name);
                }
                return database;
            }
            catch (Exception exception)
            {
                Log.LogHandler.Log.Error("获取元数据数据库列表出现问题,sql:" + sql, exception);
                return new Database();
            }

        }

        public List<Table> GetTables(string dbName = "", bool include = false)
        {
            string sql = this.GetDataTableString(dbName);
            try
            {
                Database database = null;
                List<Table> tables = Context.Sql(sql).QueryMany<Table>();
                if (include)
                {
                    if (!string.IsNullOrEmpty(dbName))
                        database = FindDataBase(dbName);
                    foreach (var table in tables)
                    {
                        table.Database = database;
                        table.Columns = GetColumns(table.Name, dbName);
                    }
                }
                return tables;
            }
            catch (Exception exception)
            {
                Log.LogHandler.Log.Error("获取元数据表列表出现问题,参数dbName:" + dbName + ",include:" + include + ",sql:" + sql, exception);
                return new List<Table>();
            }

        }

        public Table FindTable(string tbName, string dbName = "", bool include = false)
        {
            try
            {
                List<Table> tables = this.GetTables(dbName);
                Table table = tables.FirstOrDefault(t => t.Name == tbName);
                if (include && table != null)
                {
                    if (!string.IsNullOrEmpty(dbName))
                        table.Database = FindDataBase(dbName);
                    table.Columns = GetColumns(tbName, dbName);
                }
                return table;
            }
            catch (Exception exception)
            {
                Log.LogHandler.Log.Error("获取元数据表列表出现问题,参数tbName:" + tbName + ",dbName:" + dbName + ",include:" + include, exception);
                return new Table();
            }

        }

        public List<Column> GetColumns(string tbName, string dbName = "", bool include = false)
        {
            string sql = this.GetDataColumnString(tbName, dbName);
            try
            {
                List<Column> columns = Context.Sql(sql).QueryMany<Column>();
                return columns;
            }
            catch (Exception exception)
            {
                Log.LogHandler.Log.Error("获取元数据列名列表出现问题,参数tbName:" + tbName + ",dbName:" + dbName + ",include:" + include + ",sql:" + sql, exception);
                return new List<Column>();
            }

        }

        #endregion

        #region private

         

        #endregion
    }
}
